package com.hcj.springcloud.map;

/**
 * 理解代码在类中的执行顺序
 * @author huangchangjin
 */
public class Father {
    private static final Father instance = new Father(); // 1.2 【第一次实例化对象】类变量（static）会分配内存，但是实例变量不会，实例变量主要随着对象的实例化一块分配到java堆中
    private static final String first = "private static final String"; // 1.1 加载Hello类的时候,类加载器把.class文件加载到jvm的内存中，就已经初始化该值了
    private String initStr = "private String initStr"; // 1.3 【第一次实例化对象】在调用构造函数前完成  // 2.2 【第二次实例化对象】的时候调用

    public String getInitStr() {
        return initStr;
    }

    public void setInitStr(String initStr) {
        this.initStr = initStr;
    }

    public Father() {
        System.out.println("构造函数"); // 1.5 【第一次实例化对象】new 类对象的时候调用     // 2.4 【第二次实例化对象】new 类对象的时候调用
        System.out.println(first + "\n" + initStr);
    }

    static {
        System.out.println("静态代码块"); // 2.1 【第二次实例化对象】 调用类的时候，先执行“静态代码块”
        System.out.println(first); // 2.1 【第二次实例化对象】 同时可以拿到这个值
    }

    {
        System.out.println("父类非静态代码块执行"); // 1.4 【第一次实例化对象】调用构造函数前  // 2.3【第二次实例化对象】调用构造函数前
        System.out.println(first);
    }

    void run() {
        System.out.println("run 方法"); // 2.5 类对象调用方法
    }

    /**
     * 内部类: 可以是 static private public protect; 只有它被调用的时候，才会被加载，并初始化
     */
    public static class FatherStaticClass {
        private static final String first_FatherStaticClass = "private static final String"; // 1 加载Hello类的时候，就已经有值了
        private String initStr = "private String initStr"; // 3 在调用构造函数前完成

        public FatherStaticClass() {
            System.out.println("构造函数"); // 5 new 类对象的时候调用
            System.out.println(first_FatherStaticClass  + "\n" + initStr);
        }

        static {
            System.out.println("静态代码块"); // 2 调用类的时候，先执行“静态代码块”
            System.out.println(first_FatherStaticClass); // 2 同时可以拿到这个值
        }

        {
            System.out.println("父类非静态代码块执行"); // 4 调用构造函数前
            System.out.println(first_FatherStaticClass);
        }

        void run() {
            System.out.println("run 方法"); // 6 类对象调用方法
        }
    }

    public static void main(String[] args) {
        Father hello = new Father();
        hello.run();
        FatherStaticClass staticClass = new FatherStaticClass();
        staticClass.run();
    }
}
